﻿using System.Runtime.InteropServices;
using System.ComponentModel;

namespace System.Drawing.Drawing2D
{
    /// <summary>
    ///表示二维图形－圆形。
    /// </summary>
    /// <remarks>
    ///
    /// </remarks>
    [Serializable, StructLayout(LayoutKind.Sequential), ComVisible(true)]
    public struct Circle : ICloneable
    {
        private Point _pivot;//圆心
        private int _radius;//半径

        public Circle(Rectangle rect)
        {
            _pivot = GetCirclePivot(rect);
            _radius = GetCircleDiameter(rect);
        }

        public Circle(Point Pivot, int radius)
        {
            _pivot = Pivot;
            _radius = radius;
        }

        public Circle FromRectangle(Rectangle rect)
        {
            _pivot = GetCirclePivot(rect);
            _radius = GetCircleDiameter(rect);
            return this;
        }

        public static Point GetCirclePivot(Rectangle rect)
        {
            return new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
        }

        public static int GetCircleDiameter(Rectangle rect)
        {
            return Math.Min(rect.Width / 2, rect.Height / 2);
        }

        public Rectangle GetBounds()
        {
            return new Rectangle((int)(_pivot.X - _radius), (int)(_pivot.Y - _radius), (int)_radius * 2, (int)_radius * 2);
        }

        public static Rectangle GetBounds(Rectangle rect)
        {
            Point p = GetCirclePivot(rect);
            int d = GetCircleDiameter(rect);
            return new Rectangle(p.X - d, p.Y - d, d * 2, d * 2);
        }

        /// <summary>
        /// 求取两圆的圆心距
        /// </summary>
        public float Distance(Circle c)
        {
            return Distance(c.Pivot);
        }

        /// <summary>
        /// 求取指定点与该圆圆心的距离
        /// </summary>
        public float Distance(Point p)
        {
            return (float)Math.Sqrt((p.X - _pivot.X) * (p.X - _pivot.X) + (p.Y - _pivot.Y) * (p.Y - _pivot.Y));
        }

        /// <summary>
        ///     计算路径上的点坐标。
        /// </summary>
        /// <param name="sweepAngle" type="float">
        ///     <para>
        ///         极坐标下的角度。（以度为单位。）
        ///     </para>
        /// </param>
        /// <returns>
        ///     A System.Drawing.PointF value...
        /// </returns>
        public Point PointOnPath(double sweepAngle)
        {
            return new Point(_pivot.X + (int)(_radius * (float)Math.Cos(sweepAngle * (Math.PI / 180.0d))), _pivot.Y + (int)(_radius * (float)Math.Sin(sweepAngle * (Math.PI / 180.0d))));
        }

        /// <summary>
        /// 将此圆形的位置调整指定的量。
        /// </summary>
        /// <param name="x">垂直偏移该位置的量。</param>
        /// <param name="y">水平偏移该位置的量。</param>
        public void Offset(int x, int y)
        {
            _pivot.X += x;
            _pivot.Y += y;
        }

        /// <summary>
        /// 将此圆形的位置调整指定的量。
        /// </summary>
        /// <param name="pos"> 偏移该位置的量。 </param>
        public void Offset(System.Drawing.Point pos)
        {
            Offset(pos.X, pos.Y);
        }

        /// <summary>
        /// 将此 Gemini.Component.Drawing.Circle 结构放大指定量。
        /// </summary>
        /// <param name="d">半径的放大量</param>
        public void Inflate(int d)
        {
            _radius += d;
        }

        /// <summary>
        /// 测试两个  Gemini.Component.Drawing.Circle 结构的位置或大小是否不同。
        /// </summary>
        /// <param name="left">不等运算符右侧的  Gemini.Component.Drawing.Circle 结构。</param>
        /// <param name="right">不等运算符左侧的  Gemini.Component.Drawing.Circle 结构。 </param>
        /// <returns>如果两个 Gemini.Component.Drawing.Circle 结构的  Gemini.Component.Drawing.Circle.Pivot、 Gemini.Component.Drawing.Circle.Diameter 属性值中有任何一个不相等，此运算符将返回 true；否则将返回 false。</returns>
        public static bool operator ==(Circle left, Circle right)
        {
            return left._pivot == right._pivot && left._radius == right._radius;
        }

        /// <summary>
        /// 测试两个  Gemini.Component.Drawing.Circle 结构的位置或大小是否相等。
        /// </summary>
        /// <param name="left">相等运算符右侧的  Gemini.Component.Drawing.Circle 结构。</param>
        /// <param name="right">相等运算符左侧的  Gemini.Component.Drawing.Circle 结构。 </param>
        /// <returns>如果两个 Gemini.Component.Drawing.Circle 结构的  Gemini.Component.Drawing.Circle.Pivot、 Gemini.Component.Drawing.Circle.Diameter 属性值中有任何一个不相等，此运算符将返回 false；否则将返回 true。</returns>
        public static bool operator !=(Circle left, Circle right)
        {
            return !(left == right);
        }

        public override bool Equals(object obj)
        {
            return base.Equals(obj);
        }

        public static implicit operator Rectangle(Circle c)
        {
            return c.GetBounds();
        }

        public static implicit operator RectangleF(Circle c)
        {
            return (Rectangle)c;
        }

        public override int GetHashCode()
        {
            return base.GetHashCode();
        }

        public override string ToString()
        {
            return string.Format("{Pivot={0},Radius={1}}", _pivot, _radius);
        }

        #region ICloneable 成员

        public object Clone()
        {
            return new Circle(_pivot, _radius);
        }

        #endregion ICloneable 成员

        [TypeConverter(typeof(ExpandableObjectConverter))]
        public Point Pivot
        {
            get { return _pivot; }
            set { _pivot = value; }
        }

        public int Diameter
        {
            get { return _radius; }
            set { _radius = value; }
        }
    }
}